// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/prctl.h>
#include <sys/time.h>
#include <fcntl.h>
#include <thread>
#include <signal.h>
#include <sys/ioctl.h>

#include "socket_client_common.hpp"
#include "RrConfig.h"
#include "Log/logging.h"
#include "HWSecure/include/securec.h"

ReadParamsT gReadParams;
CommonClientPublic gClientInfo;
std::map<uint32_t,std::shared_ptr<CommonClient>> commonClientMap;

namespace {
    const char* ETH0_NAME = "eth0";
    constexpr int BUF_SIZE = 1024;
}

static uint64_t getCurrentTime(void)
{
    struct timeval tv;
    struct timezone tz;
    uint64_t ultime;

    gettimeofday(&tv , &tz);
    ultime = (uint64_t)(NUM_SCALE_BIG_1000(tv.tv_sec)) + (uint64_t)(NUM_SCALE_SMALL_1000(tv.tv_usec));
    return (ultime);
}


SocketClient::SocketClient()
{
    fdSock = -1;
    port = 0;
    connectCnt = 0;
    readFlag = 0;
}


SocketClient::~SocketClient()
{
    readFlag = 0;
    fdSock = -1;
}

void SocketClient::socketClientSetParamInfo(std::string ipAddr, uint16_t ipPort)
{
	strIp = ipAddr;
	port = ipPort;
	INFO("ipAddr.c_str() = %s, ipPort = %d", ipAddr.c_str(), ipPort);
}


int SocketClient::socketClientGetfdInit(void)
{
    int ret = 0;
	fdSock = socket(AF_INET, SOCK_STREAM, 0);
	if(fdSock < OK) {
		ERR("clientGetSocketFdInit error!");
		return ERROR;
	}

    struct ifreq if_ppp0;
    strncpy(if_ppp0.ifr_name, "eth0", IFNAMSIZ);

    ret = setsockopt(fdSock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&if_ppp0, sizeof(if_ppp0));
    if(ret < 0) {
        ERR("[SocketServer::SocketInit] setsockopt of SO_REUSEADDR fail, ret %d",ret);
        close(fdSock);
        return ERROR;
    }

    INFO("*****fdSock = %d", fdSock);
    return OK;
}

int SocketClient::socketClientConnectInit(int *status, int conType)
{
    int ret = OK;

    INFO("socketClientConnectInit start, connect type is %d", conType);

    struct sockaddr_in sock_addr;
    memset(&sock_addr, 0, sizeof(sock_addr));

    sock_addr.sin_family = AF_INET;
    sock_addr.sin_port = htons(port);
    inet_pton(AF_INET, strIp.c_str(), &sock_addr.sin_addr);

    if(CONNECT_FAILURE != connect(fdSock, (struct sockaddr *)&sock_addr, sizeof(sock_addr))) {
        *status = SOCKET_STATUS_CONNECT;
        connectCnt = 0;
        INFO("socketClientConnectInit connect success");
        readFlag = 1;

        return OK;
    }else{
        INFO("socketClientConnectInit connect failed, try again connectCnt = %d", connectCnt);
        usleep(CLIENT_CONNECT_DELAY_TIME_US);
        connectCnt++;
        /*如果是永久连接要无限重连直到进程关闭*/
        if((connectCnt >= MAX_TRY_CONNECT_INIT_NUM)  && (KEEP_CONNECTED_CONDITIONAL == conType)) {
            ERR("socketClientConnectInit fail");
            readFlag = 0;
            return ERROR;
        }
        readFlag = 0;
        return OK;
    }
}


int SocketClient::socketClientInit(std::string ipAddr, uint32_t ipPort)
{	
    this->socketClientSetParamInfo(ipAddr, ipPort);

    if(OK != this->socketClientGetfdInit()) {
        return ERROR;
    }
    return OK;
}

int SocketClient::socketClientReadData(uint8_t *outBuf, uint32_t *outLen, void *pArgc)
{
    int ret = OK;
    int readLen = 0;
    uint32_t readBufOffset = 0;
    int readBufLen = SOCKET_PROTOCOL_HEAD_LENGTH;
    uint32_t heatBeatTime = DEFAULT_SELECT_TIME;
    fd_set readfds;

    if((NULL == outBuf) || (NULL ==outLen)) {
        ERR("socketClientRead param failed");
        return ERROR;
    }

    CommonClient *pThis = (CommonClient *)pArgc;

    while(readFlag) {
        FD_ZERO(&readfds);
        if(fdSock > 0) {
            FD_SET(fdSock, &readfds);
        }else{
            ERR("fdSock <= 0 [%d] failed", fdSock);
            return ERROR;
        }

        struct timeval tv;
        tv.tv_sec = 0;//heatBeatTime;
        tv.tv_usec = heatBeatTime;
        
        ret = select(fdSock + 1, &readfds,NULL, NULL,&tv);
        if(ret < 0) {
            if (errno == EINTR) {
                ERR("errno == EINTR [errno %d]", errno);
                heatBeatTime = HEART_BEAT_TIME;
                // linyongzhi 先去掉老的心跳发送
                // pThis->commonClientSendHeartbeatProtocol();
                continue;
            } else if(errno != EBADF) {
                ERR("errno != EBADF");
                pThis->clientStatus = SOCKET_ERR;
                return ERROR;
            }
        }else if(ret == 0) {
            heatBeatTime = HEART_BEAT_TIME;
            DBG("select time out fdSock = %d", fdSock);
            // linyongzhi 先去掉老的心跳发送
            // pThis->commonClientSendHeartbeatProtocol();
            continue;
        }

        DBG("select ret = %d fdSock = %d", ret, fdSock);

        if((fdSock > 0) && FD_ISSET(fdSock, &readfds)) {
            DBG("FD_ISSET(fdSock = %d, &readfds)", fdSock);
            readLen = read(fdSock, outBuf + readBufOffset, readBufLen - readBufOffset);
            if(readLen < 0) {
                DBG("readLen = %d, errno = %d, readLen_ptr = %p", readLen, errno, &readLen);
                if(errno == EINTR /*|| errno == EWOULDBLOCK || errno == EAGAIN*/) {
                    ERR("readLen = %d, errno = %d", readLen, errno);
                    continue;
                }else {
                    ERR("errno == ECONNRESET error errno = %d", errno);
                    if(KEEP_CONNECTED_FOREVER == pThis->connectType) {
                        pThis->clientStatus = SOCKET_ERR;//TODO
                        return OK;
                    }else {
                        return ERROR;
                    }
                }
            }else if(readLen == 0) {
                INFO("client close the connection");
                if(KEEP_CONNECTED_FOREVER == pThis->connectType){
                    pThis->clientStatus = SOCKET_ERR;
                    return OK;
                }else{
                    return ERROR;
                }
            }

            readBufOffset += readLen;
            DBG("readBufOffset = %d, readLen = %d", readBufOffset, readLen);
            if(readBufOffset == readBufLen) {
                if(readBufOffset > SOCKET_PROTOCOL_HEAD_LENGTH){
                    readBufOffset = 0;
                    *outLen = readBufLen;
                    break;
                }else{
                    memcpy(&readBufLen, outBuf + SOCKET_PROTOCOL_HEAD_LENGTH - SOCKET_DATA_BUF_LENGTH, SOCKET_DATA_BUF_LENGTH);
                    DBG("readBufLen = %d", readBufLen);
                    if(readBufLen < 0) {
                        readFlag = 0;
                        return ERROR;
                    }
                    readBufLen += readBufOffset;
                }
            }
            DBG("readBufOffset = %d", readBufOffset);
        }
    }

    if(0 == readFlag) {
        ERR("readFlag == 0 socket fail");
        return ERROR;
    }

    return OK;
}

int SocketClient::socketClientWriteData(uint8_t *srcBuf, uint32_t srcLen, int status)
{
    uint32_t sendOffset = 0;
    int sendRetLen = 0;

    while(sendOffset < srcLen) {

        if((fdSock < 0) || (status != SOCKET_STATUS_CONNECT)) {
            ERR("socket send fail, fdSock %d",fdSock);
            return ERROR;
        }
   
        sendRetLen = send(fdSock, srcBuf + sendOffset, srcLen - sendOffset, MSG_NOSIGNAL);
        if (sendRetLen <= 0) {
            DBG("[SocketServer::socketSendThreadFunc] socket send fail, sendRetLen %d",sendRetLen);
            if(errno == EINTR /*|| errno == EWOULDBLOCK || errno == EAGAIN*/){
                ERR("socket send fail, errno %d",errno);
                //usleep(500);
                continue;
            }
            
            ERR("socket send fail, errno %d",errno);
            return ERROR;
        }

        sendOffset += sendRetLen;
    }

    DBG("socketClientWriteData write sucess end srcLen = %d",srcLen);
    return OK;
}

void SocketClient::socketClientClose(void)
{
    INFO("socketClientClose start");
    if(this->fdSock){
        close(this->fdSock);
        this->fdSock = -1;
    }
}


/******************************************CommonClient class************************************************/

CommonClient::CommonClient()
{
    contextId = DEFAULT_CONTEXT_ID;
    clientStatus = SOCKET_STATUS_IDLE;

    pSocketClient = std::make_shared<SocketClient>();

    auto pWrite = std::shared_ptr<uint8_t>(new uint8_t[SOCKET_WRITE_BUF_MAX_LENGTH], std::default_delete<uint8_t[]>());
    pWriteBuf = pWrite;
    
    auto pRead = std::shared_ptr<uint8_t>(new uint8_t[SOCKET_READ_BUF_MAX_LENGTH], std::default_delete<uint8_t[]>());
    pReadBuf = pRead;

    pOutData = nullptr;
    pOutLen = nullptr;
    readBufLen = 0;
}

CommonClient::~CommonClient()
{
}

int CommonClient::clientThreadFunc(void)
{
    int ret = OK;
    this->threadRunning = IS_RUNNING;
    this->clientStatus = SOCKET_STATUS_INIT;

    while(IS_RUNNING == threadRunning)
    {
        DBG("clientStatus = %d", clientStatus);
        switch(this->clientStatus)
        {
            case SOCKET_ERR:/*重连机制永久连接模式启用*/
            {
#if 1            
                DBG("SOCKET_ERR");
                if(0 != pSocketClient->socketClientfdParam()){
                    pSocketClient->socketClientClose();
                }
                ret = pSocketClient->socketClientGetfdInit();
                if(OK != ret){
                    return ERROR;
                }
                clientStatus = SOCKET_STATUS_INIT;
#endif
                break;
            }
            case SOCKET_STATUS_INIT:
            {
                if(OK != pSocketClient->socketClientConnectInit(&clientStatus, connectType)){
                    threadRunning = IS_OVER;
                    pSocketClient->socketClientClose();
                    this->clientStatus = SOCKET_STATUS_IDLE;
                    return ERROR;
                }
                break;
            }
            case SOCKET_STATUS_CONNECT:
            {

                if(OK != commonClientRecvDataAnalysis()){
                    if(KEEP_CONNECTED_CONDITIONAL == this->connectType){
                        threadRunning = IS_OVER;
                        pSocketClient->socketClientClose();
                        this->clientStatus = SOCKET_STATUS_IDLE;
                        return ERROR;
                    }
                }
                break;
            }
            
            default:
            break;
        }
    }
	return OK;
}

void *CommonClient::clientThreadInit(void *pArgc)
{
    CommonClient *pThis = (CommonClient *)pArgc;

    pThis->clientThreadFunc();

	return nullptr;
}

int CommonClient::createThreadInit(void)
{	
    if(OK != pthread_create(&pthreadId, NULL, clientThreadInit, this))
    {
        ERR("CreateThreadInit pthread_create fail");
        return ERROR;
    }

    return OK;
}

std::shared_ptr<CommonClient> findCommonClientIt(uint32_t contextId)
{
    std::shared_ptr<CommonClient> pCommonClient = nullptr;

    std::map<uint32_t ,std::shared_ptr<CommonClient>>::iterator commonClientIt;
    commonClientIt = commonClientMap.find(contextId);
    if(commonClientIt != commonClientMap.end()){
        if(nullptr != commonClientIt->second){
            pCommonClient = commonClientIt->second;
        }
    }else{
        DBG("findCommonClientIt context_id is not exited context_id = %d", contextId);
    }

    return pCommonClient;
}

int earseCommonClientIt(uint32_t contextId)
{
    auto pCommonClient = findCommonClientIt(contextId);
    if(nullptr == pCommonClient){
        ERR("findCommonClientIt failed,exit...");
        return ERROR;
    }

    commonClientMap.erase(contextId);
    DBG("earse commonClientMap contextId = %d", contextId);

    return OK;
}

std::shared_ptr<CommonClient> createCommonClientIt(int contextId)
{
    std::shared_ptr<CommonClient> pCommonClient;

    std::map<uint32_t ,std::shared_ptr<CommonClient>>::iterator commonClientIt;
    commonClientIt = commonClientMap.find(contextId);
    if(commonClientIt != commonClientMap.end()){
        ERR("createCommonClientIt context_id is exited failed");
        return nullptr; 
    }else{
        pCommonClient = std::make_shared<CommonClient>();
        pCommonClient->contextId = contextId;
        commonClientMap.insert(std::pair<uint32_t ,std::shared_ptr<CommonClient>>(contextId,pCommonClient));
        DBG("createCommonClientIt success");
    }

    return pCommonClient;	
}

int CommonClient::dealConfig(const std::string configFilePath)
{
    rr::RrConfig config;
    
    if(!config.ReadConfig(configFilePath))
    {
        ERR("Read config file failed, use the default configuration");
        return ERROR;
    }

    //本机内网IP
    if (0 != getIP(ETH0_NAME, rr::gClientConfig.iSocketWorker.ipAddr)) {
        ERR("Read worker private ip failed.");
    }
    rr::gClientConfig.iSocketClient.ipAddr = rr::gClientConfig.iSocketWorker.ipAddr;
    rr::gClientConfig.iSocketClient.port =
            config.ReadInt("SOCKET_MASTER", "port", DEFAULT_PORT);
    rr::gClientConfig.iSocketClient.timeOut =
            config.ReadInt("SOCKET_MASTER", "time_out", DEFAULT_TIMES_OUT);

    return OK;
}

int CommonClient::commonClientInit(std::string strIp, uint16_t port, uint32_t timeOut, int conType)//与集群连接
{
    int ret = OK;

    if(SOCKET_STATUS_IDLE != clientStatus){
        ERR("clientStatus is no SOCKET_STATUS_IDLE");
        return ERROR;
    }

    pthreadTimeOut = timeOut;

    ret = pSocketClient->socketClientInit(strIp, port);
    if(OK != ret){
        ERR("socketClientInit ret[%d] fail", ret);
        return ERROR;
    }
    this->clientStatus = SOCKET_STATUS_INIT;
    this->connectType = conType;

    ret = this->createThreadInit();
    if(OK != ret){
        ERR("CreateThreadInit fail");
        return ERROR;
    }

    while(1)
    {
        usleep(CLIENT_CONNECT_DELAY_TIME_US);
        if(SOCKET_STATUS_CONNECT == clientStatus){
            DBG("SocketClientInit OK");
            ret = OK;
            break;
        } else if(this->clientStatus == SOCKET_STATUS_IDLE){
            ERR("clientStatus is no SOCKET_STATUS_IDLE");
            return ERROR;
        }
    }

    return ret;
}

int CommonClient::commonClientRecvDataAnalysis(void)
{
    uint16_t cmdCtl = 0;

    if(OK != pSocketClient->socketClientReadData(pReadBuf.get(), &readBufLen,  this)){
        ERR("socketClientRead fail , get out socket");
        pSocketClient->readFlag = 0;
        return ERROR;
    }

    DBG("*****readBufLen = %d", readBufLen);

    if(OK == memcmp(pReadBuf.get(), &SOCKET_HEAD_FLAG, SOCKET_HEAD_FLAG_LENGTH))
    {
        memcpy(&cmdCtl, pReadBuf.get() + SOCKET_HEAD_FLAG_LENGTH, SOCKET_CMD_LENGTH);
        DBG("cmdCtl = 0x%x, this->cmd 0x%x", cmdCtl, this->cmd);

        // 未注册回调函数，先注释
        // (*gReadParams.callBackFunc)(cmdCtl, pReadBuf.get() + SOCKET_HEAD_CMD_LENGTH, readBufLen - SOCKET_HEAD_CMD_LENGTH);
    }
    return OK;
}

int CommonClient::commonClientWrite(uint16_t cmdCtl, uint8_t *inBuf, uint32_t inLen)
{
	if((NULL == inBuf) || (inLen < 0) || (inLen > SOCKET_READ_BUF_MAX_LENGTH - SOCKET_BUF_BLOCK)){
		ERR("CommonClientWrite param failure %s %d",inBuf,inLen);
		return ERROR;
	}

	int ret = OK;
	memcpy(pWriteBuf.get(), &SOCKET_HEAD_FLAG, SOCKET_HEAD_FLAG_LENGTH);
    memcpy(pWriteBuf.get() + SOCKET_HEAD_FLAG_LENGTH, &cmdCtl, SOCKET_CMD_LENGTH);
	memcpy(pWriteBuf.get() + SOCKET_HEAD_FLAG_LENGTH + SOCKET_CMD_LENGTH, &inLen, SOCKET_DATA_BUF_LENGTH);
	memcpy(pWriteBuf.get() + SOCKET_PROTOCOL_HEAD_LENGTH, inBuf, inLen);

	writeBufLen = SOCKET_PROTOCOL_HEAD_LENGTH + inLen;

	ret = pSocketClient->socketClientWriteData(pWriteBuf.get(), writeBufLen, this->clientStatus);
	if(OK != ret){
		ERR("SocketClientWrite fail");
        if(KEEP_CONNECTED_CONDITIONAL != this->connectType){
            this->clientStatus = SOCKET_ERR;
        }
        pSocketClient->readFlag = 0;
		return ERROR;
	}

	return ret;
}

int CommonClient::commonClientSendHeartbeatProtocol(void)
{
    HeartbeatParamT gHeart;

    gHeart.timestamp = getCurrentTime();
    gHeart.heartIndex++;

    if(OK != this->commonClientWrite(SOCKET_HEARTBEAT, (uint8_t *)&gHeart, sizeof(HeartbeatParamT))){
        ERR("commonClientWrite SOCKET_DECODE_CLOSE_REQ failed");
        return ERROR;
    }

    return OK;
}

int CommonClient::getIP(const std::string &net_name, std::string &strIP)
{
    int sock_fd;
    struct ifconf conf;
    struct ifreq *ifr;
    char buff[BUF_SIZE] = {0};
    int num;
    int i;
 
    sock_fd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sock_fd < 0) {
        ERR("Failed to create socket, errno=%d", errno);
        return -1;
    }
 
    conf.ifc_len = BUF_SIZE;
    conf.ifc_buf = buff;
 
    if (ioctl(sock_fd, SIOCGIFCONF, &conf) < 0) {
        ERR("Failed to set ifconf, errno=%d", errno);
        close(sock_fd);
        return -1;
    }
 
    num = conf.ifc_len / sizeof(struct ifreq);
    ifr = conf.ifc_req;
 
    for (i = 0; i < num; i++) {
        struct sockaddr_in *sin = (struct sockaddr_in *)(&ifr->ifr_addr);
 
        if (ioctl(sock_fd, SIOCGIFFLAGS, ifr) < 0) {
            ERR("Failed to get ifflags, errno=%d", errno);
            close(sock_fd);
            return -1;
        }
 
        if ((ifr->ifr_flags & IFF_UP) && strcmp(net_name.c_str(),ifr->ifr_name) == 0) {
            strIP = inet_ntoa(sin->sin_addr);
            close(sock_fd);
            INFO("Got ip %s.", strIP.c_str());
            return 0;
        }
		
        ifr++;
    }
	
    close(sock_fd);
    return -1;
}

/*************************************************************************/

CommonClientPublic::CommonClientPublic()
{
}
CommonClientPublic::~CommonClientPublic()
{
}

int CommonClientPublic::connectMasterInit(std::string configFileName, uint32_t port, const std::string& encodeType,
                                          const std::string& videoFrameType, const std::string& resolution, const std::string& fps)
{
    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sa, 0);

    /*连上集群的IP*/
    auto pClient = findCommonClientIt(DEFAULT_CONTEXT_ID);//集群固定contextId, 如果没连上，则先连上，如果连上了，上报负载能力
    if(nullptr == pClient){
        pClient = createCommonClientIt(DEFAULT_CONTEXT_ID);
        if(nullptr == pClient){
            ERR("createCommonClientIt fail...");
            return ERROR;
        }

        if(OK != pClient->dealConfig(configFileName)){
            ERR("Read config file failed");
            return ERROR;
        }
        rr::gClientConfig.iSocketWorker.port = port;
        rr::gClientConfig.resourceType = ENCODE_POOL_ENCODE;
        rr::gClientConfig.status = ENCODE_POOL_WORKER_IDLE;

        if (encodeType == "CPU") {
            rr::gClientConfig.encodeType = ENCODE_POOL_CPU;
        } else if (encodeType == "GPU") {
            rr::gClientConfig.encodeType = ENCODE_POOL_GPU;
        }

        if (videoFrameType == "H264") {
            rr::gClientConfig.dataType = ENCODE_POOL_H264;
        } else if (videoFrameType == "H265") {
            rr::gClientConfig.dataType = ENCODE_POOL_H265;
        } else if (videoFrameType == "MIX") {
            rr::gClientConfig.dataType = ENCODE_POOL_MIX;
        }
        if (resolution == "720P") {
            rr::gClientConfig.flavorType = ENCODE_POOL_720P;
        } else if (resolution == "1080P") {
            rr::gClientConfig.flavorType = ENCODE_POOL_1080P;
        }

        rr::gClientConfig.frameRate = std::stoi(fps);

        char workerKeyBuffer[rr::WORKER_KEY_LENGTH_MAX];
        (void)memset_s(workerKeyBuffer, rr::WORKER_KEY_LENGTH_MAX, 0, rr::WORKER_KEY_LENGTH_MAX);
        snprintf_s(workerKeyBuffer, rr::WORKER_KEY_LENGTH_MAX, rr::WORKER_KEY_LENGTH_MAX, "%s:%d:%d:%d:%d:%d:%d", rr::gClientConfig.iSocketWorker.ipAddr.c_str(),
        rr::gClientConfig.iSocketWorker.port, rr::gClientConfig.encodeType, rr::gClientConfig.resourceType, rr::gClientConfig.dataType, rr::gClientConfig.flavorType, rr::gClientConfig.frameRate);
        rr::gClientConfig.workerKey = workerKeyBuffer;

        INFO("Worker key is: %s, Master Info ip: %s, port : %d", rr::gClientConfig.workerKey.c_str(),
        rr::gClientConfig.iSocketClient.ipAddr.c_str(), rr::gClientConfig.iSocketClient.port);
        
        if(OK != pClient->commonClientInit(rr::gClientConfig.iSocketClient.ipAddr, 
                rr::gClientConfig.iSocketClient.port, rr::gClientConfig.iSocketClient.timeOut, KEEP_CONNECTED_FOREVER)){
            ERR("commonClientInit fail...");
            return ERROR;
        }
    }

    return reportStatus(rr::gClientConfig.status);
}

int CommonClientPublic::sendCmdData(uint16_t cmdCtl, uint8_t *inData, uint32_t inLen)
{
    if((nullptr == inData) || (inLen <= 0)){
        ERR("openEncode params fail...");
        return ERROR;
    }

    auto pClient = findCommonClientIt(DEFAULT_CONTEXT_ID);
    if(nullptr == pClient){
        ERR("pClient is not exist...");
        return ERROR;
    }

    if(pClient->clientStatus != SOCKET_STATUS_CONNECT){
        ERR("******this->clientStatus = %d", pClient->clientStatus);
        return ERROR;
    }

    if(OK != pClient->commonClientWrite(cmdCtl, inData, inLen)){
        ERR("commonClientWrite failed, cmd is %d", cmdCtl);
        return ERROR;
    }

    return OK;
}

int CommonClientPublic::reportStatus(uint32_t status)
{
    RemoteWorkerStatusReq remoteWorkerStatusReq;
    strcpy(remoteWorkerStatusReq.workerIp, rr::gClientConfig.iSocketWorker.ipAddr.c_str());
    strcpy(remoteWorkerStatusReq.workerUuid, rr::gClientConfig.workerKey.c_str());
    remoteWorkerStatusReq.port = rr::gClientConfig.iSocketWorker.port;
    remoteWorkerStatusReq.status = status;
    remoteWorkerStatusReq.encodeType = rr::gClientConfig.encodeType;
    remoteWorkerStatusReq.resourceType = rr::gClientConfig.resourceType;
    remoteWorkerStatusReq.dataType = rr::gClientConfig.dataType;
    remoteWorkerStatusReq.flavorType = rr::gClientConfig.flavorType;
    remoteWorkerStatusReq.frameRate = rr::gClientConfig.frameRate;

    INFO("Report worker status, ip: %s, port: %d, status: %d", remoteWorkerStatusReq.workerIp, remoteWorkerStatusReq.port, remoteWorkerStatusReq.status);
    return sendCmdData(SOCKET_WORKER_STATUS_REPORT, reinterpret_cast<uint8_t *>(&remoteWorkerStatusReq), REMOTE_WORKER_STATUS_REQ_SIZE);
}

int CommonClientPublic::reportHeartbeat()
{
    RemoteWorkerStatusReq remoteWorkerStatusReq;
    strcpy(remoteWorkerStatusReq.workerIp, rr::gClientConfig.iSocketWorker.ipAddr.c_str());
    strcpy(remoteWorkerStatusReq.workerUuid, rr::gClientConfig.workerKey.c_str());
    remoteWorkerStatusReq.port = rr::gClientConfig.iSocketWorker.port;
    remoteWorkerStatusReq.status = rr::gClientConfig.status;
    remoteWorkerStatusReq.encodeType = rr::gClientConfig.encodeType;
    remoteWorkerStatusReq.resourceType = rr::gClientConfig.resourceType;
    remoteWorkerStatusReq.dataType = rr::gClientConfig.dataType;
    remoteWorkerStatusReq.flavorType = rr::gClientConfig.flavorType;
    remoteWorkerStatusReq.frameRate = rr::gClientConfig.frameRate;

    DBG("Report heartbeat, ip: %s, port: %d, status: %d", remoteWorkerStatusReq.workerIp, remoteWorkerStatusReq.port, remoteWorkerStatusReq.status);
    return sendCmdData(SOCKET_HEARTBEAT, reinterpret_cast<uint8_t *>(&remoteWorkerStatusReq), REMOTE_WORKER_STATUS_REQ_SIZE);
}

/*
 * 描述: 回调注册入口函数
 * 参数: callbackFun 注册函数 pArgc 参数，没有置为空
 * 返回值: 空
 */ 
void socketClientRegCallbackRead(callbackClientRead callbackFunc, void* pArgc)
{
    gReadParams.callBackFunc = callbackFunc;
    gReadParams.params = pArgc;
}